#ifndef THREAD_THREAD_H
#define THREAD_THREAD_H
#include "stdint.h"
#include "list.h"
#include "bitmap.h"
#include "memory.h"

typedef void thread_func(void*);
typedef int16_t pid_t;
#define TASK_NAME_LEN 16
#define MAX_FILES_OPEN_PER_PROC 8

enum task_status {
    TASK_RUNNING,
    TASK_READY,
    TASK_BLOCKED,
    TASK_WAITING,
    TASK_HANGING,
    TASK_DIED
};

// 中断栈. 发生中断时, 保存上下文
struct intr_stack 
{
    uint32_t vec_no;
    uint32_t edi;
    uint32_t esi;
    uint32_t ebp;
    uint32_t esp_dummy;
    uint32_t ebx;
    uint32_t edx;
    uint32_t ecx;
    uint32_t eax;
    uint32_t gs;
    uint32_t fs;
    uint32_t es;
    uint32_t ds;

    uint32_t err_code;
    void (*eip) (void);    // old_eip
    uint32_t cs;     // old_cs
    uint32_t eflags; // old_eflags
    void* esp;    // old_esp
    uint32_t ss;  // old_ss
};

// 线程栈
struct thread_stack {
    uint32_t ebp;
    uint32_t ebx;
    uint32_t edi;
    uint32_t esi;

    void (*eip) (thread_func* func, void* func_arg);

    void (*unused_retaddr);    // 无用, 占位
    thread_func* func;    // 线程开始运行函数
    void* func_arg;    // 函数参数
};

// 程序控制块PCB
struct task_struct 
{
    uint32_t* self_kstack;    // 进程内核栈
    pid_t pid;
    enum task_status status;
    char name[TASK_NAME_LEN];
    uint8_t priority;    // 线程优先级
    uint8_t ticks;    // 每次处理器上执行的时间嘀嗒数
    uint32_t elapsed_ticks;    // 从运行至今所用嘀嗒数
    int32_t fd_table[MAX_FILES_OPEN_PER_PROC]; // 单元内保存文件表file_table下标
                                               // 该数组下标为文件描述符

    struct list_elem general_tag;    // 用于加入就绪队列等
    struct list_elem all_list_tag;    // 用于加入全部线程队列
    uint32_t* pgdir;    // 进程自己页表的虚拟地址

    struct virtual_addr userprog_vaddr; // 用户进程的虚拟地址
    struct mem_block_desc u_block_desc[DESC_CNT];
    
    uint32_t cwd_inode_no;  // 进程所在的工作目录的inode编号
    int16_t parent_pid;
    int8_t exit_status; // 子进程退出状态
    uint32_t stack_magic; // 检测栈的溢出, 必须位于最后
};

extern struct list thread_ready_list;    // 就绪队列
extern struct list thread_all_list;    // 所有任务队列

void release_pid(pid_t pid);
struct task_struct* thread_start(char* name, int prio, thread_func func, void* func_arg);
void init_thread(struct task_struct* pthread, char* name, int prio);
void thread_create(struct task_struct* pthread, thread_func func, void* func_arg);
void thread_exit(struct task_struct* thread_over, bool need_schedule);
struct task_struct* pid2thread(int32_t pid);

void thread_init();    // 初始化thread功能
struct task_struct* running_thread();
void schedule();

void thread_block(enum task_status stat);
void thread_unblock(struct task_struct* pthread);

void thread_yield();
pid_t fork_pid();
void sys_ps();
#endif //THREAD_THREAD_H
